﻿// Lesson23.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <algorithm>
#include <numeric>
#include <string>
#include <functional>
#include <execution>

//#define NOMINMAX
//#include <Windows.h>

int is_jishu(int v)
{
	return v % 2 != 0;
}

struct jishu
{
	jishu(int nV)
		:nValue(nV)
	{

	}
	int nValue;
	bool operator()(int v)
	{
		return v % nValue == 0;
	}
};

std::string stringcat(std::string a, std::string b)  {
	return std::move(a) + "," + std::string(b);
}

void vec_int_print(int x)
{
	
	std::cout <<"i["<< x << "] ";
}

void vec_double_print(double x)
{
	std::cout <<"d["<< x << "] ";
}

typedef void(* pint_print)(int);
typedef void(*pdouble_print)(int);





void process(const std::vector<int>& vec, std::function<void(int)> callback)
{
	for (size_t i = 0; i < vec.size(); i++)
	{
		callback(vec[i]);
	}
	std::cout << std::endl;
}

auto multiplyBy2Functor(int x)
{
	return [x]() { return 2 * x; };
}


class binder_class
{
public:
	binder_class(const std::string& objName)
		:mObjName(objName)
	{

	}
	int print_self(std::string x)
	{
		std::cout << mObjName<<" "<< x << std::endl;
		return 0;
	}
private:
	std::string mObjName;
};


void removeEmptyStrings(std::vector<std::string>& strings)
{
	auto it=std::remove_if(std::begin(strings), std::end(strings), [](const std::string& str) {
		return str.empty();
	});
	strings.erase(it,std::end(strings));
}


int main()
{
	std::vector<int> container{2,4,3,7,1,9,15,20,6,5,3};

	std::function<void(int)> callback = reinterpret_cast<void(*)(double)>(vec_int_print);
	process(container, callback);

	int init_value = 333;

	auto lambda_func = 
	[=](int x)->void {
		//init_value = 99;
		//container;
		std::cout << init_value<<"," << x << std::endl;
	};

	struct lambda_func_noname
	{
		int init_value;
		lambda_func_noname(int init_val)
			:init_value(init_val)
		{

		}
		void operator()(int x) const
		{
			std::cout << init_value << "," << x << std::endl;
		}
	};

	lambda_func_noname(333)(888);

	lambda_func(888);

	auto fbind = std::bind(stringcat, std::placeholders::_2, std::placeholders::_1);

	std::cout << fbind("Hello","World") << std::endl;

	binder_class bc("Hello");
	auto memfunc = std::bind(&binder_class::print_self,&bc, std::placeholders::_1);//bc.print_self(args);
	memfunc("9012");

	//auto fIter = std::find(container.begin()+3, container.begin() + 8, 3);
	//if (fIter == (container.begin() + 8))
	//{
	//	std::cout << "not found:" << std::endl;
	//}
	//else
	//{
	//	std::cout << "find it:"<< std::distance(container.begin(), fIter) << std::endl;
	//}
	jishu jishux(5);
	auto nIter = std::find_if(container.begin(), container.end(), /*is_jishu*/jishux);
	if (nIter == container.end())
	{
		std::cout << "not found:" << std::endl;
	}
	else
	{
		std::cout << "find it:" << *nIter << std::endl;
	}


	auto sum = std::accumulate(container.begin(), container.end(), 0);

	std::cout << "sum =" << sum << std::endl;

	//join

	std::vector<std::string> strvec = {"one","two","three",""};

	std::find_if(std::begin(strvec), std::end(strvec), std::not_fn(std::mem_fn(&std::string::empty)));

	std::function<std::string(std::string,std::string)> fstrcat = stringcat;
	auto strs = std::accumulate(std::next(strvec.begin()), strvec.end(), strvec.front(),
		/*stringcat*/fstrcat
		);

	std::cout << "strs =" << strs << std::endl;

	std::function<int(int)> f1 = is_jishu;

	std::cout<<"7 is jishu?"<<f1(7)<<std::endl;

	std::vector<int> intcontainer{ 2,4,3,7,1,9,15,20,6,5,3 };
	std::vector<double> doublecontainer{ 2.1,5.5,3.0,7.9,4.2,3.8 };

	auto isGreaterThan4 = [](auto i) {return i > 4; };

	std::find_if(std::cbegin(intcontainer), std::cend(intcontainer), isGreaterThan4);

	//std::find_if(std::cbegin(doublecontainer), std::cend(doublecontainer), isGreaterThan4);

	std::find_if(std::cbegin(doublecontainer), std::cend(doublecontainer),std::bind(std::greater<>(),std::placeholders::_1,4));

	double pi = 3.14;
	[myCapture = "Pi:", pi](){std::cout << myCapture << pi << std::endl; }();

	auto fn = multiplyBy2Functor(5);

	int nValue = 4;
	std::count_if(std::cbegin(intcontainer), std::cend(intcontainer), [nValue](int value) {return value > nValue; });
	int init_val=1;
	std::generate(std::begin(intcontainer), std::end(intcontainer), [&init_val]() { init_val = init_val * 2; return init_val; });
	for (size_t i = 0; i < intcontainer.size(); i++)
	{
		std::cout << intcontainer[i] << " ";
	}
	std::cout << "--------------------------------" << std::endl;
	std::cout<<fn()<<std::endl;

	std::plus<int> int_plus;

	int xvalue = int_plus(4, 5);
	std::cout << xvalue << std::endl;

	std::accumulate(std::begin(intcontainer),std::end(intcontainer),1.2,std::multiplies<>());

	std::equal_to<>()(3,4);

	std::invoke(&vec_int_print, 2);

	std::invoke(&vec_double_print, 3.14);

	std::invoke(&std::string::size, std::string("hello"));


	std::string in = "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
		" sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
	std::string needle = "pisci";
	auto it = std::search(in.begin(), in.end(),
		std::boyer_moore_searcher(
			needle.begin(), needle.end()));
	if (it != in.end())
		std::cout << "The string " << needle << " found at offset "
		<< it - in.begin() << '\n';
	else
		std::cout << "The string " << needle << " not found\n";
	std::string c = "c";
	std::string c0 = "c0";
	std::string v1 = "c1";
	std::string v20 = "c20";
	std::vector<std::string> sarr = {"c0", "c" ,"c2" ,"c20" };
	std::sort(sarr.begin(), sarr.end(), 
		[](std::string v1, std::string v2) { 
		return std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end()); }
	);
	for (size_t i = 0; i < sarr.size(); i++)
	{
		std::cout << sarr[i] << " ";
	}
	std::cout << std::endl;
	//std::lexicographical_compare(v1.begin(), v1.end(), v2.begin(), v2.end());

	(std::min)(1, 2);

	std::sort(std::execution::par, sarr.begin(), sarr.end());



	return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
